/**
 * @file auto_nombre.c
 * @author François Portet <francois.portet@imag.fr>
 * @author Florian Castellane <florian.castellane@phelma.grenoble-inp.fr
 * @author Christian Proust <christian.proust@phelma.grenoble-inp.fr>
 * @date Thu Sep 13 12:00:00 2012
 * @brief Fonction de l'automate détectant les différents types de représentation de nombre entier.
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#include "include/auto_nombre.h"
#include "include/gestiondetypes.h"
#include "include/gestiondesmessages.h"


/**
 * @param ligne chaîne de caractères à analyser
 * @param i index du caractère en faute
 * @param c code ascii du caractère en faute
 * @return -1
 * @brief message d'erreur généré lorsqu'une erreur de décodage apparaît
 *
 *
 */

TYPE_DE_LEXEME erreur_caractere ( const char *ligne , int i , int c, unsigned int numeroligne)
{
    ecriremessage(NIVEAU_ERROR,"Ligne %d : Erreur au caractere en position %d, << %c >> de la chaine << %s >>.\n",numeroligne, i,c,ligne);
    return TYPE_Erreur;
}


/**
 * @param ligne chaîne de caractères à classifier
 * @return le type de lexème en cas de succès, le type erreur sinon
 * @brief fonction qui met en œuvre l'automate de classification de chaîne de caractères
 *
 */


TYPE_DE_LEXEME classifie_nombre(const char* ligne, unsigned int numeroligne)
{
    unsigned int S = INIT;
    unsigned int i=0;

    for (i=0; i<=strlen(ligne); i++)
    {
        char c=ligne[i];
        switch (S)
        {
        case INIT :
    /**/    if (isdigit(c))              /* si c est un chiffre */
    /**/    {
    /**/        S = ( c== '0' ) ? PRE_HEXA : DECIMAL ;
    /**/        if(S==PRE_HEXA && (i== strlen(ligne)-1 || isspace(ligne[i+1]) || ligne[i+1]=='\0'))
    /**/        {
    /**/            S = DECIMAL ;/* cas ou le nombre est 0*/
    /**/        }
    /**/    }
    /**/    else if ( isspace(c) || c=='\0') S=INIT ;
    /**/    else return erreur_caractere (ligne , i , c , numeroligne);
    /**/    break ;
        case PRE_HEXA: /* repérage du préfixe de l hexa */
    /**/    if ( c == 'x' || c == 'X' ) S=HEXA ;
    /**/    else if (isdigit(c) && c < '8' ) /* c est un octal */
    /**/        S=OCTAL ;
    /**/
    /**/    else return erreur_caractere (ligne, i , c , numeroligne);
    /**/    break ;
        case DEBUT_HEXA : /* il faut au moins un chiffre après x */
    /**/    if (isxdigit(c)) S=HEXA ;
    /**/    else return erreur_caractere (ligne, i , c , numeroligne);
    /**/    break ;
        case HEXA : /* tant que c est un chiffre hexa */
    /**/    if ( isxdigit(c)) S=HEXA ;
    /**/    else if ( isspace(c) || c=='\0' )
    /**/    {
    /**/        return TYPE_Valeur_hexadecimale;
    /**/    }
    /**/    else return erreur_caractere ( ligne , i , c , numeroligne);
    /**/    break ;
        case DECIMAL : /* tant que c est un chiffre */
    /**/    if (isdigit(c))      S=DECIMAL ;
    /**/    else if ( isspace(c)  || c=='\0')
    /**/    {
    /**/        return TYPE_Valeur_decimale;
    /**/    }
    /**/    else
    /**/        return erreur_caractere ( ligne , i , c , numeroligne);
    /**/    break ;
        case OCTAL: /* tant que c est un chiffre */
    /**/    if ( isdigit(c)&& c < '8') S=OCTAL ;
    /**/    else if ( isspace(c) || c=='\0')
    /**/    {
    /**/        return TYPE_Valeur_octale;
    /**/    }
    /**/    else
    /**/        return erreur_caractere ( ligne , i , c , numeroligne);
    /**/    break;
        }
    }
    return TYPE_Erreur;
}
